import React from 'react';
// import { render } from 'react-dom';
// import { Link, Route } from 'react-router-dom'
// import Home from './pages/Home'
// import List from './pages/List'
// import axios from 'axios'
import ReactDOM from 'react-dom'

// useState
// function App(props) {
//   // const propsCount = props.count || 0 只在组件第一次被渲染时才有意义
//   const [count, setCount] = useState(() => {
//     // 只有在第一次渲染执行 在组件更新时就不会再执行
//     return props.count || 0
//   })
//   const [person, setPerson] = useState({name: '张三', age: 20})
//   function handleCount () {
//     setCount(() => {
//       document.title = count + 1
//       return count + 1
//     })
//     // 拿到的值是未改变之前的值  说明是异步的
//     // document.title = count
//   }
//   return <div>
//     {count} {person.name} {person.age}
//     {/* 调用 setCount 方法修改状态 */}
//     <button onClick={() => setCount(handleCount)}>+1</button>
//     {/* 如果只修改单一数据，需要将原本的数据注入到对象中 */}
//     <button onClick={() => setPerson({...person, name: '李四'})}>setPerson</button>
//   </div>;
// }

// useReducer
// function reducer (state, action) {
//   switch (action.type) {
//     case 'increment':
//       return state + 1
//     case 'decrement':
//       return state - 1
//     default:
//       return state
//   }
// }

// function App () {
//   const [count, dispatch] = useReducer(reducer, 0)
//   return <div>
//     <span>{ count }</span>
//     <button onClick={() => dispatch({type: 'increment'})}>+1</button>
//     <button onClick={() => dispatch({type: 'decrement'})}>-1</button>
//   </div>
// }


// useContext
// const countContext = createContext()

// function App () {
//   return <countContext.Provider value={100}>
//     <Foo />
//   </countContext.Provider>
// }

// // 简化前
// // function Foo () {
// //   return <countContext.Consumer>
// //     {
// //       value => {
// //         return <div>{ value }</div>
// //       }
// //     }
// //   </countContext.Consumer>
// // }

// // 简化后
// function Foo () {
//   const value = useContext(countContext)
//   console.log(value)
//   return <div>{ value }</div>
// }


// useEffect
// function App () {
//   const [count, setCount] = useState(0)
//   // 组件挂载完成之后执行  组件数据更新完成之后执行
//   useEffect(() => {
//     console.log('123')
//   })

//   // 组件挂载完成之后执行
//   useEffect(() => {
//     console.log('123')
//   }, [])

//   // 组件被卸载之前执行
//   useEffect(() => () => {
//     console.log('组件被卸载')
//   })
//   return <div>
//     {count}
//     <button onClick={() => setCount(count + 1)}>+1</button>
//     <button onClick={() => ReactDOM.unmountComponentAtNode(document.getElementById('root'))}>卸载组件</button>
//   </div>
// }

// function App () {
//   function onScroll () {
//     console.log('页面发生滚动了')
//   }
//   useEffect(() => {
//     window.addEventListener('scroll', onScroll)
//     return () => {
//       window.removeEventListener('scroll', onScroll)
//     }
//   }, [])

//   const [count, setCount] = useState(0)
//   useEffect(() => {
//     const timerId = setInterval(() => {
//       setCount(count => count + 1)
//     }, 1000);
//     return () => {
//       clearInterval(timerId)
//     }
//   }, [])
//   return <div>
//     { count }
//     <button onClick={() => ReactDOM.unmountComponentAtNode(document.getElementById('root'))}>卸载组件</button>
//   </div>
// }

// function App () {
//   const [count, setCount] = useState(0)
//   const [person, setPerson] = useState({name: '张三'})
//   useEffect (() => {
//     document.title = count
//   }, [count]) // 只有 count 发生变化时会触发
//   return <div>
//     { count }
//     <button onClick={() => setCount(count + 1)}>+1</button>
//     <button onClick={() => setPerson({name: '李四'})}>setPerson</button>
//   </div>
// }

// function App () {
//   useEffect (() => {
//     getData().then(result => {
//       console.log(result)
//     })
//   })
//   // useEffect 必须返回一个函数用于在组件被销毁之前执行
//   useEffect (() => {
//     (async () => {
//       const result = await getData()
//       console.log(result)
//     })()
//   }, [])
//   return <div>
//   </div>
// }

// function getData () {
//   return new Promise(res => {
//     setTimeout(() => {
//       res('success')
//     }, 1000);
//   })
// }


// useMemo
// function App () {
//   const [count, setCount] = useState(0)
//   const [bool, setBool] = useState(true)
//   const result = useMemo(() => {
//     console.log(1)
//     return count * 2
//   }, [count])
//   return <div>
//   {count} * 2 = {result}
//   {bool ? '真' : '假'}
//   <button onClick={() => setCount(count + 1)}>+1</button>
//   <button onClick={() => setBool(!bool)}>setBool</button>
//   </div>
// }


// memo useCallback
// function App () {
//   const [count, setCount] = useState(0)
//   // 获取相同的函数实例，Foo 组件就不会重新渲染
//   const resetCount = useCallback(() => setCount(0), [setCount])
//   // 在 App 组件重新渲染时 resetCount 也会更新，Foo 组件内部也会被重新渲染
//   // const resetCount = () => {
//   //   setCount(0)
//   // }
//   return <div>
//   {count}
//   <button onClick={() => setCount(count + 1)}>+1</button>
//   <Foo resetCount={resetCount} />
//   </div>
// }

// // function Foo () {
// //   console.log('Foo 重新渲染') // 每次 App 组件重新渲染时都会执行
// //   return <div>Foo 组件</div>
// // }

// const Foo = memo(function (props) {
//   console.log('Foo 重新渲染') // App 组件重新渲染时不会再执行
//   return <div>
//     Foo 组件
//     <button onClick={() => props.resetCount()}>resetCount</button>
//   </div>
// })

// useRef
// function App () {
//   const box = useRef()
//   return <div ref={box}>
//     <button onClick={() => console.log(box)}>box</button>
//   </div>
// }

// function App () {
//   const [count, setCount] = useState(0)
//   // 在 count 被修改时，组件重新渲染，timerId 又为 null，所以无法停止定时器
//   // let timerId = null
//   // 使用 useRef 创建的数据在组件重新渲染后仍然存在
//   let timerId = useRef()
//   useEffect(() => {
//     timerId.current = setInterval(() => {
//       setCount(count => count + 1)
//     }, 1000);
//   }, [])
  
//   const stopCount = () => {
//     console.log(timerId)
//     clearInterval(timerId.current)
//   }
//   return <div>
//     {count}
//     <button onClick={stopCount}>stopCount</button>
//   </div>
// }


// 将获取文章数据提取到自定义 Hook 函数中
// function useGetPost () {
//   const [post, setPost] = useState({})
//   useEffect(() => {
//     axios.get('https://jsonplaceholder.typicode.com/posts/1')
//       .then(response => setPost(response.data))
//   }, [])
//   return [post, setPost]
// }

// function App () {
//   const [post, setPost] = useGetPost()
//   return <div>
//     <div>{post.title}</div>
//     <div>{post.body}</div>
//   </div>
// }

// function useUpdateInput (initialValue) {
//   const [value, setValue] = useState(initialValue)
//   return {
//     value,
//     onChange: event => setValue(event.target.value)
//   }
// }

// function App () {
//   const usernameInput = useUpdateInput('')
//   const passwordInput = useUpdateInput('')
//   const submitForm = event => {
//     event.preventDefault()
//     console.log(usernameInput.value, passwordInput.value)
//   }
//   return <form onSubmit={submitForm}>
//     <input type='text' name='username' {...usernameInput} />
//     <input type='password' name='password' {...passwordInput} />
//     <input type='submit' />
//   </form>
// }


// Router Hooks
// function App () {
//   return <div>
//     <div>
//       <Link to="/home/tom">首页</Link>
//       <Link to="/list">列表</Link>
//     </div>
//     <div>
//       <Route path="/home/:name" component={Home} />
//       <Route path="/list" component={List} />
//     </div>
//   </div>
// }
let state = []
let setters = []
let stateIndex = 0

function createSetter (index) {
  // 返回修改状态的方法
  return function (newState) {
    state[index] = newState
    // 修改状态后重新渲染
    render()
  }
}
function useState (initialValue) {
  state[stateIndex] = state[stateIndex] ? state[stateIndex] : initialValue
  // 将修改状态的方法添加到 setters 中
  setters.push(createSetter(stateIndex))
  let value = state[stateIndex]
  let setter = setters[stateIndex]
  stateIndex++
  return [value, setter]
}

function render () {
  // 在重新渲染时下标归零
  stateIndex = 0
  effectIndex = 0
  ReactDOM.render(<App />, document.getElementById('root'))
}

let prevDepsAry = []
let effectIndex = 0

function useEffect (callback, depsAry) {
  // 判断 callback 是否是函数
  if (Object.prototype.toString.call(callback) !== '[object Function]') throw new Error('useEffect 第一个参数必须是函数')
  // 判断 depsAry 有没有传递
  if (typeof depsAry === 'undefined') {
    // 没有传递
    callback()
  } else {
    // 判断 depsAry 是否是数组
    if (Object.prototype.toString.call(depsAry) !== '[object Array]') throw new Error('useEffect 第二个参数必须是数组')
    // 获取上一次的状态值
    let preDeps = prevDepsAry[effectIndex]
    // 将当前的依赖值和上一次的依赖症做对比  如果有变化  调用 callback
    let hasChanged = preDeps ? depsAry.every((dep, index) => dep === preDeps[index]) === false : true
    // 判断是否有变化
    if (hasChanged) {
      callback()
    }
    // 同步依赖值
    prevDepsAry[effectIndex] = depsAry
    effectIndex++
  }
}

function useReducer(reducer, initialValue) {
  const [state, setState] = useState(initialValue)
  function dispatch (action) {
    // 获取使用 reducer 方法的返回值
    const newState = reducer(state, action)
    // 使用 setState 来修改状态值
    setState(newState)
  }
  return [state, dispatch]
}

function App () {
  function reducer (state, action) {
    switch (action.type) {
      case 'increment':
        return state + 1
      case 'decrement':
        return state - 1
      default:
        return state
    }
  }
  const [count, dispatch] = useReducer(reducer, 0)
  return <div>
    {count}
    <button onClick={() => dispatch({type: 'increment'})}>+1</button>
    <button onClick={() => dispatch({type: 'decrement'})}>-1</button>
  </div>
}

export default App;